package com.example.myapplication;

import android.app.Activity;
import android.os.Environment;
import android.util.Log;
import android.view.Display;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.FrameLayout;

import androidx.annotation.NonNull;

import org.java_websocket.handshake.ServerHandshake;

import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Arrays;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;

public class MediaPlayHelper implements SocketClientListener {

    String url = "";
    private URI wssUrl = null;
    private SocketClient sockeClient;
    private MediaCodecUtil mediaCodecUtil;
    private ByteBuf videoBuffer = Unpooled.buffer();
    private SurfaceView surfaceView;
    private Activity activity;
    private AudioReader audioReader;
    private static MediaPlayHelper replayUtil;

    public MediaPlayHelper(SurfaceView surfaceView, Activity activity, String url) {
        this.surfaceView = surfaceView;
        this.activity = activity;
        this.url = url;
        init();
    }

    public static MediaPlayHelper getInstance(SurfaceView surfaceView, Activity activity, String url) {
        if (replayUtil == null) {
            synchronized (MediaPlayHelper.class) {
                if (replayUtil == null) {
                    replayUtil = new MediaPlayHelper(surfaceView, activity, url);
                }
            }
        }
        return replayUtil;
    }

    public void init() {
        try {
            initSocketClient();
            G726Util.init();
            audioReader = new AudioReader();
            audioReader.init();
            Display display = activity.getWindowManager().getDefaultDisplay();
            int width = display.getWidth();
            int height = display.getHeight();
            FrameLayout.LayoutParams params = new FrameLayout.LayoutParams(width, width * 9 / 16);
            surfaceView.setLayoutParams(params);
            surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
                @Override
                public void surfaceCreated(@NonNull SurfaceHolder surfaceHolder) {
                    mediaCodecUtil = new MediaCodecUtil(surfaceHolder);
                    mediaCodecUtil.startCodec();
                }

                @Override
                public void surfaceChanged(@NonNull SurfaceHolder surfaceHolder, int i, int i1, int i2) {

                }

                @Override
                public void surfaceDestroyed(@NonNull SurfaceHolder surfaceHolder) {

                }
            });
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
    }

    public void initSocketClient() throws URISyntaxException {
        wssUrl = new URI(url);
        sockeClient = new SocketClient(wssUrl);
        sockeClient.setSocketClientListener(this);

    }

    public void startConnect() {
        try {
            closeConnect();
            initSocketClient();
            sockeClient.connectBlocking();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }
    }

    /**
     * 断开连接
     */
    public void closeConnect() {
        try {
            if (null != sockeClient) {
                sockeClient.close();
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            sockeClient = null;
        }
    }


    /**
     * 转码为H264格式的码流/G726格式的音频
     *
     * @param bytes
     */
    private void decode(ByteBuffer bytes) {
        byte[] rawArray = bytes.array();
        ByteBuf byteBuf = Unpooled.wrappedBuffer(rawArray);

        while (byteBuf.isReadable()) {
            //帧头
            byteBuf.skipBytes(5);

            byte mAndPtByte = byteBuf.readByte();
            int isComplete = mAndPtByte >>> 7;
            int payloadType = mAndPtByte & 0x7f;

            //跳过序列号
            byteBuf.skipBytes(2);
            byte[] rawTerminalId = byteBuf.readBytes(6).array();

            int channel = byteBuf.readByte() & 0x01;
            byte dataTypeAndSubFlagByte = byteBuf.readByte();
            int dataType = (dataTypeAndSubFlagByte >> 4) & 0x0f;
            int subPacketFlag = (dataTypeAndSubFlagByte >> 4) & 0x0f;

            long timeStampMillis = byteBuf.readLong();

            if (payloadType == 98) {
                int lastIFrameInterval = byteBuf.readShort();
                int lastFrameInterval = byteBuf.readShort();
                int bodyLength = byteBuf.readUnsignedShort();
                videoBuffer.writeBytes(byteBuf.readBytes(bodyLength));
                if (isComplete > 0) {
                    //结束，输出到视频解码器,h264格式的视频
                    byte[] videoFrameByteArray = videoBuffer.array();
//                    onReceiveVideoData(videoFrameByteArray);
                    mediaCodecUtil.onFrame(videoFrameByteArray, 0, videoFrameByteArray.length);
                    videoBuffer.clear();
                }
            } else {
                int bodyLength = byteBuf.readShort();
                //如果是音频，那么直接输出到音频解码器,G726 40k码率 8000采样频率 5bit 采样位数
                byte[] audioFrameByteArray = byteBuf.readBytes(bodyLength).array();

//                writeFile(PATH, audioFrameByteArray);
                short[] tempByte = new short[audioFrameByteArray.length * 6];
                if (payloadType == 6 || payloadType == 7) {
                    G726Util.g711decode(tempByte,
                            audioFrameByteArray,
                            audioFrameByteArray.length, payloadType);
                } else {
                    G726Util.decode(tempByte,
                            audioFrameByteArray,
                            audioFrameByteArray.length);
                }
                Log.e("########", "tempByte:" + tempByte.length + "");
                short[] standardShort = Arrays.copyOf(tempByte, 160);
                Log.e("########", "standardShort:" + standardShort.length + "");
                writeFile(PATH, standardShort);
                audioReader.playAudioTrack(tempByte, 0, 160);

            }
        }
    }

    public static String PATH = Environment.getExternalStorageDirectory().getAbsolutePath() + "/testOutput.pcm";


    /**
     * 把数据流写入文件
     *
     * @param path
     * @param bytes
     */
    private void writeFile(String path, short[] bytes) {
        try {

            FileOutputStream out = new FileOutputStream(path, true);//指定写到哪个路径中
            FileChannel fileChannel = out.getChannel();
            fileChannel.write(ByteBuffer.wrap(InputStreamUtils.shortArray2ByteArray(bytes))); //将字节流写入文件中
            fileChannel.force(true);//强制刷新
            fileChannel.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onOpen(ServerHandshake handshakedata) {

    }

    @Override
    public void onMessage(ByteBuffer bytes) {
        decode(bytes);
    }

    @Override
    public void onMessage(String message) {

    }

    @Override
    public void onClose(int code, String reason, boolean remote) {

    }

    @Override
    public void onError(Exception ex) {

    }
}
